

#include "ili9341_lcd.h"
#include "pinctrl.h"
#include "watchdog.h"
#include "gpio.h"
#include "spi.h"
#include "tcxo.h"
#include "soc_osal.h"
#include "gui.h"

#define CONFIG_SPI_DI_PIN 11
#define CONFIG_SPI_DO_PIN 9
#define CONFIG_SPI_CLK_PIN 7
#define CONFIG_SPI_CS_PIN 8
#define CONFIG_SPI_MASTER_PIN_MODE 3
#define CONFIG_SPI_DC_PIN 1
#define CONFIG_SPI_RST_PIN 14
#define CONFIG_SPI_BLK_PIN 12
#define CONFIG_GPIO_PIN_MODE 0

#define SPI_SLAVE_NUM 1
#define SPI_BUS_CLK 64000000
#define SPI_FREQ_MHZ 32
#define SPI_CLK_POLARITY 0
#define SPI_CLK_PHASE 0
#define SPI_FRAME_FORMAT 0
#define SPI_FRAME_FORMAT_STANDARD 0
#define SPI_TMOD 0
#define SPI_WAIT_CYCLES 0x10

_lcd_dev lcddev;

uint16_t POINT_COLOR = 0x0000, BACK_COLOR = 0xFFFF;
uint16_t DeviceCode;

// 帧缓冲区
uint16_t* frame_buffer = NULL;

void LCD_RESET(void)
{
    uapi_gpio_set_val(CONFIG_SPI_RST_PIN, GPIO_LEVEL_LOW);
    osal_msleep(100);
    uapi_gpio_set_val(CONFIG_SPI_RST_PIN, GPIO_LEVEL_HIGH);
    osal_msleep(50);
}

void LCD_WR_REG(uint8_t data)
{
    uapi_gpio_set_val(CONFIG_SPI_CS_PIN, GPIO_LEVEL_LOW);
    uapi_gpio_set_val(CONFIG_SPI_DC_PIN, GPIO_LEVEL_LOW);
    spi_xfer_data_t xfer = {
        .tx_buff = &data,
        .tx_bytes = 1,
    };
    errcode_t ret = uapi_spi_master_write(SPI_BUS_0, &xfer, 1000);
    if (ret != ERRCODE_SUCC) {
        printf("SPI send failed: 0x%x\n", ret);
        ret = uapi_spi_master_write(SPI_BUS_0, &xfer, 1000);
    }
    uapi_gpio_set_val(CONFIG_SPI_CS_PIN, GPIO_LEVEL_HIGH);
}

void LCD_WR_DATA(uint8_t data)
{
    uapi_gpio_set_val(CONFIG_SPI_CS_PIN, GPIO_LEVEL_LOW);
    uapi_gpio_set_val(CONFIG_SPI_DC_PIN, GPIO_LEVEL_HIGH);
    spi_xfer_data_t xfer = {
        .tx_buff = &data,
        .tx_bytes = 1,
    };
    errcode_t ret = uapi_spi_master_write(SPI_BUS_0, &xfer, 1000);
    if (ret != ERRCODE_SUCC) {
        printf("SPI send failed: 0x%x\n", ret);
    }
    uapi_gpio_set_val(CONFIG_SPI_CS_PIN, GPIO_LEVEL_HIGH);
}

void LCD_WriteReg(uint8_t LCD_Reg, uint16_t LCD_RegValue)
{
    LCD_WR_REG(LCD_Reg);
    LCD_WR_DATA(LCD_RegValue);
}

void LCD_WriteRAM_Prepare(void)
{
    LCD_WR_REG(lcddev.wramcmd); // 写GRAM命令
}

void Lcd_WriteData_16Bit(uint16_t data)
{
    uapi_gpio_set_val(CONFIG_SPI_CS_PIN, GPIO_LEVEL_LOW);
    uapi_gpio_set_val(CONFIG_SPI_DC_PIN, GPIO_LEVEL_HIGH);
    LCD_WR_DATA(data >> 8);
    LCD_WR_DATA(data);
    uapi_gpio_set_val(CONFIG_SPI_CS_PIN, GPIO_LEVEL_HIGH);
}

void LCD_WriteData_Array(uint8_t *data, uint32_t len)
{
    uapi_gpio_set_val(CONFIG_SPI_CS_PIN, GPIO_LEVEL_LOW);
    uapi_gpio_set_val(CONFIG_SPI_DC_PIN, GPIO_LEVEL_HIGH);
    spi_xfer_data_t xfer = {
        .tx_buff = data,
        .tx_bytes = len,
    };
    errcode_t ret = uapi_spi_master_write(SPI_BUS_0, &xfer, 0xffffff);
    if (ret != ERRCODE_SUCC) {
        printf("SPI send failed: 0x%x\n", ret);
    }
    uapi_gpio_set_val(CONFIG_SPI_CS_PIN, GPIO_LEVEL_HIGH);
}

// pin初始化
void app_spi_gpio_init_pin(void)
{
    uapi_pin_set_mode(CONFIG_SPI_DI_PIN, CONFIG_SPI_MASTER_PIN_MODE);
    uapi_pin_set_mode(CONFIG_SPI_DO_PIN, CONFIG_SPI_MASTER_PIN_MODE);
    uapi_pin_set_mode(CONFIG_SPI_CLK_PIN, CONFIG_SPI_MASTER_PIN_MODE);
    uapi_pin_set_mode(CONFIG_SPI_CS_PIN, CONFIG_GPIO_PIN_MODE);
    uapi_gpio_set_dir(CONFIG_SPI_CS_PIN, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_val(CONFIG_SPI_CS_PIN, GPIO_LEVEL_HIGH);
    uapi_pin_set_mode(CONFIG_SPI_DC_PIN, CONFIG_GPIO_PIN_MODE);
    uapi_gpio_set_dir(CONFIG_SPI_DC_PIN, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_val(CONFIG_SPI_DC_PIN, GPIO_LEVEL_HIGH);
    uapi_pin_set_mode(CONFIG_SPI_RST_PIN, CONFIG_GPIO_PIN_MODE);
    uapi_gpio_set_dir(CONFIG_SPI_RST_PIN, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_val(CONFIG_SPI_RST_PIN, GPIO_LEVEL_HIGH);
    uapi_pin_set_mode(CONFIG_SPI_BLK_PIN, CONFIG_GPIO_PIN_MODE);
    uapi_gpio_set_dir(CONFIG_SPI_BLK_PIN, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_val(CONFIG_SPI_BLK_PIN, GPIO_LEVEL_HIGH);
}

void spi_init(void)
{
    spi_attr_t config = {0};
    spi_extra_attr_t ext_config = {0};

    config.is_slave = false;
    config.slave_num = SPI_SLAVE_NUM;
    config.bus_clk = SPI_BUS_CLK;
    config.freq_mhz = SPI_FREQ_MHZ;
    config.clk_polarity = SPI_CLK_POLARITY;
    config.clk_phase = SPI_CLK_PHASE;
    config.frame_format = SPI_FRAME_FORMAT;
    config.spi_frame_format = HAL_SPI_FRAME_FORMAT_STANDARD;
    config.frame_size = HAL_SPI_FRAME_SIZE_8;
    config.tmod = SPI_TMOD;
    config.sste = 0;

    //ext_config.tx_use_dma = true;
    ext_config.sspi_param.wait_cycles = SPI_WAIT_CYCLES;
    int ret = uapi_spi_init(SPI_BUS_0, &config, &ext_config);
    if (ret != 0) {
        printf("spi init fail %0x\r\n", ret);
    }
    printf("SPI freq =%dMHz\n", config.freq_mhz);
    uapi_dma_init();
    // uapi_dma_open();
    //  spi_dma_config_t dma_cfg = {
    //     .src_width = 0,
    //     .dest_width = 0,
    //     .burst_length = 3,
    //     .priority = 3
    // };
    // if (uapi_spi_set_dma_mode(SPI_BUS_0, true, &dma_cfg) != ERRCODE_SUCC) {
    //     osal_printk("spi%d master set dma mode fail!\r\n");
    // }
}

void LCD_DrawPoint(uint16_t x, uint16_t y)
{
    LCD_SetCursor(x, y);
    Lcd_WriteData_16Bit(POINT_COLOR);
}

void LCD_Clear(uint16_t Color)
{
    unsigned int i, m;
    LCD_SetWindows(0, 0, lcddev.width - 1, lcddev.height - 1);
    uapi_gpio_set_val(CONFIG_SPI_CS_PIN, GPIO_LEVEL_LOW);
    uapi_gpio_set_val(CONFIG_SPI_DC_PIN, GPIO_LEVEL_HIGH);
    for (i = 0; i < lcddev.height; i++) {
        for (m = 0; m < lcddev.width; m++) {
            Lcd_WriteData_16Bit(Color);
        }
    }
    uapi_gpio_set_val(CONFIG_SPI_CS_PIN, GPIO_LEVEL_HIGH);
}

void LCD_Fill_Clear(uint16_t Color)
{
    unsigned int i, m;
    LCD_SetWindows(0, 0, lcddev.width - 1, lcddev.height - 1);
    uapi_gpio_set_val(CONFIG_SPI_CS_PIN, GPIO_LEVEL_LOW);
    uapi_gpio_set_val(CONFIG_SPI_DC_PIN, GPIO_LEVEL_HIGH);
    // for (i = 0; i < lcddev.height; i++) {
    //     for (m = 0; m < lcddev.width; m++) {
    //         Lcd_WriteData_16Bit(Color);
    //     }
    // }

    uapi_gpio_set_val(CONFIG_SPI_CS_PIN, GPIO_LEVEL_HIGH);
}

void LCD_SetWindows(uint16_t xStar, uint16_t yStar, uint16_t xEnd, uint16_t yEnd)
{
    LCD_WR_REG(lcddev.setxcmd);
    LCD_WR_DATA(xStar >> 8);
    LCD_WR_DATA(0x00FF & xStar);
    LCD_WR_DATA(xEnd >> 8);
    LCD_WR_DATA(0x00FF & xEnd);

    LCD_WR_REG(lcddev.setycmd);
    LCD_WR_DATA(yStar >> 8);
    LCD_WR_DATA(0x00FF & yStar);
    LCD_WR_DATA(yEnd >> 8);
    LCD_WR_DATA(0x00FF & yEnd);

    LCD_WriteRAM_Prepare();
}

void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
{
    LCD_SetWindows(Xpos, Ypos, Xpos, Ypos);
}

void LCD_direction(uint8_t direction)
{
    lcddev.setxcmd = 0x2A;
    lcddev.setycmd = 0x2B;
    lcddev.wramcmd = 0x2C;
    switch (direction) {
        case 0:
            lcddev.width = LCD_W;
            lcddev.height = LCD_H;
            LCD_WriteReg(0x36, (1 << 3) | (0 << 6) | (0 << 7)); // BGR==1,MY==0,MX==0,MV==0
            break;
        case 1:
            lcddev.width = LCD_H;
            lcddev.height = LCD_W;
            LCD_WriteReg(0x36, (1 << 3) | (0 << 7) | (1 << 6) | (1 << 5)); // BGR==1,MY==1,MX==0,MV==1
            break;
        case 2:
            lcddev.width = LCD_W;
            lcddev.height = LCD_H;
            LCD_WriteReg(0x36, (1 << 3) | (1 << 6) | (1 << 7)); // BGR==1,MY==0,MX==0,MV==0
            break;
        case 3:
            lcddev.width = LCD_H;
            lcddev.height = LCD_W;
            LCD_WriteReg(0x36, (1 << 3) | (1 << 7) | (1 << 5)); // BGR==1,MY==1,MX==0,MV==1
            break;
        default:
            break;
    }
}

void LCD_Init(void)
{
    app_spi_gpio_init_pin();
    spi_init();
    LCD_RESET(); // LCD ��λ
    LCD_WR_REG(0xCF);
    LCD_WR_DATA(0x00);
    LCD_WR_DATA(0xD9); // C1
    LCD_WR_DATA(0X30);
    LCD_WR_REG(0xED);
    LCD_WR_DATA(0x64);
    LCD_WR_DATA(0x03);
    LCD_WR_DATA(0X12);
    LCD_WR_DATA(0X81);
    LCD_WR_REG(0xE8);
    LCD_WR_DATA(0x85);
    LCD_WR_DATA(0x10);
    LCD_WR_DATA(0x7A);
    LCD_WR_REG(0xCB);
    LCD_WR_DATA(0x39);
    LCD_WR_DATA(0x2C);
    LCD_WR_DATA(0x00);
    LCD_WR_DATA(0x34);
    LCD_WR_DATA(0x02);
    LCD_WR_REG(0xF7);
    LCD_WR_DATA(0x20);
    LCD_WR_REG(0xEA);
    LCD_WR_DATA(0x00);
    LCD_WR_DATA(0x00);
    LCD_WR_REG(0xC0);  // Power control
    LCD_WR_DATA(0x1B); // VRH[5:0]
    LCD_WR_REG(0xC1);  // Power control
    LCD_WR_DATA(0x12); // SAP[2:0];BT[3:0] //0x01
    LCD_WR_REG(0xC5);  // VCM control
    LCD_WR_DATA(0x26); // 3F
    LCD_WR_DATA(0x26); // 3C
    LCD_WR_REG(0xC7);  // VCM control2
    LCD_WR_DATA(0XB0);
    LCD_WR_REG(0x36); // Memory Access Control
    LCD_WR_DATA(0x08);
    LCD_WR_REG(0x3A);
    LCD_WR_DATA(0x55);
    LCD_WR_REG(0xB1);
    LCD_WR_DATA(0x00);
    LCD_WR_DATA(0x1A);
    LCD_WR_REG(0xB6); // Display Function Control
    LCD_WR_DATA(0x0A);
    LCD_WR_DATA(0xA2);
    LCD_WR_REG(0xF2); // 3Gamma Function Disable
    LCD_WR_DATA(0x00);
    LCD_WR_REG(0x26); // Gamma curve selected
    LCD_WR_DATA(0x01);
    LCD_WR_REG(0xE0); // Set Gamma
    LCD_WR_DATA(0x1F);
    LCD_WR_DATA(0x24);
    LCD_WR_DATA(0x24);
    LCD_WR_DATA(0x0D);
    LCD_WR_DATA(0x12);
    LCD_WR_DATA(0x09);
    LCD_WR_DATA(0x52);
    LCD_WR_DATA(0xB7);
    LCD_WR_DATA(0x3F);
    LCD_WR_DATA(0x0C);
    LCD_WR_DATA(0x15);
    LCD_WR_DATA(0x06);
    LCD_WR_DATA(0x0E);
    LCD_WR_DATA(0x08);
    LCD_WR_DATA(0x00);
    LCD_WR_REG(0XE1); // Set Gamma
    LCD_WR_DATA(0x00);
    LCD_WR_DATA(0x1B);
    LCD_WR_DATA(0x1B);
    LCD_WR_DATA(0x02);
    LCD_WR_DATA(0x0E);
    LCD_WR_DATA(0x06);
    LCD_WR_DATA(0x2E);
    LCD_WR_DATA(0x48);
    LCD_WR_DATA(0x3F);
    LCD_WR_DATA(0x03);
    LCD_WR_DATA(0x0A);
    LCD_WR_DATA(0x09);
    LCD_WR_DATA(0x31);
    LCD_WR_DATA(0x37);
    LCD_WR_DATA(0x1F);

    LCD_WR_REG(0x2B);
    LCD_WR_DATA(0x00);
    LCD_WR_DATA(0x00);
    LCD_WR_DATA(0x01);
    LCD_WR_DATA(0x3f);
    LCD_WR_REG(0x2A);
    LCD_WR_DATA(0x00);
    LCD_WR_DATA(0x00);
    LCD_WR_DATA(0x00);
    LCD_WR_DATA(0xef);
    LCD_WR_REG(0x11); // Exit Sleep
    osal_msleep(120);
    LCD_WR_REG(0x29); // display on
    LCD_direction(USE_HORIZONTAL);
    uapi_gpio_set_val(CONFIG_SPI_BLK_PIN, GPIO_LEVEL_HIGH);
    LCD_Fill_Clear(WHITE);
}
